﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Kimd.Common
{
    public class ProxyModelHelper
    {
        private AppDomain ad;
        public Dictionary<string, ProxyObject> AllProxyObjects;

        public ProxyModelHelper()
        {
            ad = AppDomain.CreateDomain("DLL Unload test");
            AllProxyObjects = new Dictionary<string, ProxyObject>();
        }

        public void LoadDll(string dir)
        {
            string callingDomainName = AppDomain.CurrentDomain.FriendlyName;//Thread.GetDomain().FriendlyName; 
            Console.WriteLine(callingDomainName);
            string addInDir = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
            var UserAssembliesFiles = Directory.EnumerateFiles(addInDir + $"\\{dir}", "*.dll");
            foreach (string assemblyFilePath in UserAssembliesFiles)
            {
                ProxyObject obj = (ProxyObject)ad.CreateInstanceFromAndUnwrap("Kimd.Common.dll", "Kimd.Common.ProxyObject");
                obj.LoadAssembly(assemblyFilePath);
                AllProxyObjects.Add(Path.GetFileNameWithoutExtension(assemblyFilePath), obj);
            }
            //obj.Invoke("TestDll.Class1", "Test", "It's a test");
        }

        public void UnLoadDll()
        {
            AppDomain.Unload(ad);
            AllProxyObjects.Clear();
        }
    }

    public class ProxyObject : MarshalByRefObject
    {
        public Assembly assembly;

        public void LoadAssembly(string path)
        {
            assembly = Assembly.LoadFile(path);
        }
        public bool Invoke(string fullClassName, string methodName, params Object[] args)
        {
            if (assembly == null)
                return false;
            Type tp = assembly.GetType(fullClassName);
            if (tp == null)
                return false;
            MethodInfo method = tp.GetMethod(methodName);
            if (method == null)
                return false;
            Object obj = Activator.CreateInstance(tp);
            method.Invoke(obj, args);
            return true;
        }
    }
}
